package com.bjsdzk.collector.serviceImp;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.bjsdzk.collector.entity.telecom.TelecomToken;
import com.bjsdzk.collector.platform.coap.utils.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;

@Service
public class TelecomSecondService {
	
	private static Logger logger = LoggerFactory.getLogger(TelecomSecondService.class);

    @Autowired
    private MongoTemplate mongoTemplate;
    
	public static List<String> accessToken =new ArrayList<>(8);
    public static List<String>  refreshToken=new ArrayList<>(8) ;
	
	
    @SuppressWarnings({ "unchecked", "resource" })
	public List<String>  getToken() throws Exception  {

        List<String> appid = ConstantSecond.APPID;
        List<String> secrets = ConstantSecond.SECRET;
        String urlLogin = ConstantSecond.APP_AUTH;
        for (int i = 0; i < appid.size(); i++) {
            String appId =appid.get(i);
            String secret = secrets.get(i);
            HttpsUtil httpsUtil = new HttpsUtil();
            httpsUtil.initSSLConfigForTwoWay();

            Map<String, String> paramLogin = new HashMap<>();
            paramLogin.put("appId", appId);
            paramLogin.put("secret", secret);

            StreamClosedHttpResponse responseLogin = httpsUtil.doPostFormUrlEncodedGetStatusLine(urlLogin, paramLogin);

            logger.info("appId:{},secret:{},getToken: response content:"+responseLogin.getContent(),appId,secret);

            Map<String, String> data = new HashMap<>();
            data = JsonUtil.jsonString2SimpleObj(responseLogin.getContent(), data.getClass());
            accessToken.add(i, data.get("accessToken"));
            refreshToken.add(i, data.get("refreshToken"));
        }
          return accessToken;
	}
    
    @SuppressWarnings({ "unchecked", "resource" })
    public List<String>  refreshToken() throws Exception {
        // Two-Way Authentication
        HttpsUtil httpsUtil = new HttpsUtil();
        httpsUtil.initSSLConfigForTwoWay();

        List<String> appid = ConstantSecond.APPID;
        List<String> secrets = ConstantSecond.SECRET;

        String urlRefreshToken = ConstantSecond.REFRESH_TOKEN;
        for (int i = 0; i < appid.size(); i++) {
            String appId =appid.get(i);
            String secret = secrets.get(i);
            Map<String, Object> param_reg = new HashMap<>();
            param_reg.put("appId", appId);
            param_reg.put("secret", secret);
            param_reg.put("refreshToken", refreshToken.get(i));

            String jsonRequest = JsonUtil.jsonObj2Sting(param_reg);
            StreamClosedHttpResponse bodyRefreshToken = httpsUtil.doPostJsonGetStatusLine(urlRefreshToken, jsonRequest);

            Map<String, String> data = new HashMap<>();
            data = JsonUtil.jsonString2SimpleObj(bodyRefreshToken.getContent(), data.getClass());
            logger.info("appId:{},secret:{},refreshToken: response content:"+bodyRefreshToken.getContent(),appId,secret);
            accessToken.add(i, data.get("accessToken"));
            refreshToken.add(i, data.get("refreshToken"));
        }
        return accessToken;
    }
    

    /**4.3.3 查询设备历史数据*/
    @SuppressWarnings({  "resource" })
    public String queryDataHistory(String deviceId,String gatewayId,String pageNo,String pageSize,String startTime,String endTime,String appId) throws Exception {
 	   // Two-Way Authentication
     HttpsUtil httpsUtil = new HttpsUtil();
     httpsUtil.initSSLConfigForTwoWay();


     //Please make sure that the following parameter values have been modified in the ConstantSecond file.
     String urlQueryDeviceHistoryData = ConstantSecond.QUERY_DEVICE_HISTORY_DATA;

     Map<String, String> paramQueryDeviceHistoryData = new HashMap<>();
     paramQueryDeviceHistoryData.put("deviceId", deviceId);
     paramQueryDeviceHistoryData.put("gatewayId", gatewayId);
     paramQueryDeviceHistoryData.put("pageNo", pageNo);
     paramQueryDeviceHistoryData.put("pageSize", pageSize);
     if(StringUtils.isNotEmpty(startTime)&&StringUtils.isNotEmpty(startTime)) {
    	 paramQueryDeviceHistoryData.put("startTime", startTime);
    	 paramQueryDeviceHistoryData.put("endTime", endTime);
     }
     Map<String, String> header = new HashMap<>();
     header.put(ConstantSecond.HEADER_APP_KEY, appId);
     header.put(ConstantSecond.HEADER_APP_AUTH, "Bearer" + " " + accessToken);
     
     StreamClosedHttpResponse bodyQueryDeviceHistoryData = httpsUtil.doGetWithParasGetStatusLine(
             urlQueryDeviceHistoryData, paramQueryDeviceHistoryData, header);

     logger.info("StatusLine:"+bodyQueryDeviceHistoryData.getStatusLine()+" response content:"+bodyQueryDeviceHistoryData.getContent());
     return bodyQueryDeviceHistoryData.getContent();
 }
    

    /**注册设备
     * @return
     * @throws Exception
     */
    @SuppressWarnings({ "resource" })
    public String regDirectDevice(String verifyCode,String nodeId,String name,String location,String appId) throws Exception {
        HttpsUtil httpsUtil = new HttpsUtil();
        httpsUtil.initSSLConfigForTwoWay();


        //Please make sure that the following parameter values have been modified in the ConstantSecond file.
		String urlReg = ConstantSecond.REGISTER_DEVICE;

        //please replace the verifyCode and nodeId and timeout, when you use the demo.
        Integer timeout = 0;
        
        Map<String, Object> paramModifyDeviceInfo = new HashMap<>();
        paramModifyDeviceInfo.put("name", name);
        paramModifyDeviceInfo.put("manufacturerId", "bhsiot");
        paramModifyDeviceInfo.put("manufacturerName", "bhsiot");
        paramModifyDeviceInfo.put("location", location);
        paramModifyDeviceInfo.put("deviceType", "bhside2");
        paramModifyDeviceInfo.put("model", "bhside23");
        paramModifyDeviceInfo.put("protocolType", "CoAP");
        

        Map<String, Object> paramReg = new HashMap<>();
        paramReg.put("verifyCode", verifyCode.toUpperCase());
        paramReg.put("nodeId", nodeId.toUpperCase());
        paramReg.put("timeout", timeout);
        paramReg.put("deviceInfo", paramModifyDeviceInfo);

        String jsonRequest = JsonUtil.jsonObj2Sting(paramReg);

        Map<String, String> header = new HashMap<>();
        header.put(ConstantSecond.HEADER_APP_KEY, appId);
        header.put(ConstantSecond.HEADER_APP_AUTH, "Bearer" + " " + accessToken);

        StreamClosedHttpResponse responseReg = httpsUtil.doPostJsonGetStatusLine(urlReg, header, jsonRequest);

        logger.info("StatusLine:"+responseReg.getStatusLine()+" response content:"+responseReg.getContent());
        return responseReg.getContent();
    }
    
    /**注册设备
     * @return
     * @throws Exception
     */
    @SuppressWarnings({ "resource" })
    public String rk_regDirectDevice(String verifyCode,String nodeId,String name,String location,String appId) throws Exception {
        HttpsUtil httpsUtil = new HttpsUtil();
        httpsUtil.initSSLConfigForTwoWay();


        //Please make sure that the following parameter values have been modified in the ConstantSecond file.
		String urlReg = ConstantSecond.REGISTER_DEVICE;

        //please replace the verifyCode and nodeId and timeout, when you use the demo.
        Integer timeout = 0;
        
        Map<String, Object> paramModifyDeviceInfo = new HashMap<>();
        paramModifyDeviceInfo.put("name", name);
        paramModifyDeviceInfo.put("manufacturerId", "bhsiot");
        paramModifyDeviceInfo.put("manufacturerName", "bhsiot");
        paramModifyDeviceInfo.put("location", location);
        paramModifyDeviceInfo.put("deviceType", "bhside2");
        paramModifyDeviceInfo.put("model", "bhside23");
        paramModifyDeviceInfo.put("protocolType", "CoAP");

        Map<String, Object> paramReg = new HashMap<>();
        paramReg.put("verifyCode", verifyCode.toUpperCase());
        paramReg.put("nodeId", nodeId.toUpperCase());
        paramReg.put("timeout", timeout);
        paramReg.put("deviceInfo", paramModifyDeviceInfo);

        String jsonRequest = JsonUtil.jsonObj2Sting(paramReg);

        Map<String, String> header = new HashMap<>();
        header.put(ConstantSecond.HEADER_APP_KEY, appId);
        header.put(ConstantSecond.HEADER_APP_AUTH, "Bearer" + " " + accessToken);

        StreamClosedHttpResponse responseReg = httpsUtil.doPostJsonGetStatusLine(urlReg, header, jsonRequest);

        logger.info("StatusLine:"+responseReg.getStatusLine()+" response content:"+responseReg.getContent());
        return responseReg.getContent();
    }

    public  String cmd(String deviceId,String serviceId,String method,int fDetectorAddress,int fDetectorType,int fCommandType,Integer fValue,String appId)  throws Exception {

        // Two-Way Authentication
        HttpsUtil httpsUtil = new HttpsUtil();
        httpsUtil.initSSLConfigForTwoWay();

        // Authentication，get token

        //Please make sure that the following parameter values have been modified in the ConstantSecond file.
        String urlPostAsynCmd = ConstantSecond.POST_ASYN_CMD;

        //please replace the deviceId, when you use the demo.
        String callbackUrl = ConstantSecond.REPORT_CMD_EXEC_RESULT_CALLBACK_URL;

//        String serviceId = "detectorStatus";
//        String method = "QueryStatus";
        int fCheckSum;
        JsonNodeFactory nodeFactory = new JsonNodeFactory(false);
        ObjectNode paras = new ObjectNode(nodeFactory);
	      paras.put("fDetectorAddress", fDetectorAddress);
	      paras.put("fDetectorType", fDetectorType);
	      paras.put("fCommandType", fCommandType);
	      fCheckSum=fCommandType+fDetectorType+fDetectorAddress;
	      if(fValue!=null) {
	    	  paras.put("fValue", fValue); 
	    	  fCheckSum=fValue+fCommandType+fDetectorType+fDetectorAddress;
	      }
	      paras.put("fCheckSum", fCheckSum);
//        paras.put("fDetectorAddress", 1);
//        paras.put("fDetectorType", 4);
//        paras.put("fCommandType", 1);
//        paras.put("fCheckSum", 6);
        
        Map<String, Object> paramCommand = new HashMap<>();
        paramCommand.put("serviceId", serviceId);
        paramCommand.put("method", method);
        paramCommand.put("paras", paras);      
        
        Map<String, Object> paramPostAsynCmd = new HashMap<>();
        paramPostAsynCmd.put("deviceId", deviceId);
        paramPostAsynCmd.put("command", paramCommand);
        paramPostAsynCmd.put("callbackUrl", callbackUrl);
        paramPostAsynCmd.put("expireTime", 0);
        paramPostAsynCmd.put("maxRetransmit", 2);
        
        String jsonRequest = JsonUtil.jsonObj2Sting(paramPostAsynCmd);
                
        Map<String, String> header = new HashMap<>();
        header.put(ConstantSecond.HEADER_APP_KEY, appId);
        header.put(ConstantSecond.HEADER_APP_AUTH, "Bearer" + " " + accessToken);
        
        HttpResponse responsePostAsynCmd = httpsUtil.doPostJson(urlPostAsynCmd, header, jsonRequest);

        String responseBody = httpsUtil.getHttpResponseBody(responsePostAsynCmd);

        logger.info("StatusLine:"+responsePostAsynCmd.getStatusLine()+" Content:"+responseBody);
        return responseBody;
    }

    public String deleteDirectDevice(String deviceId,String deviceType) throws Exception {

        TelecomToken token = getAppId(deviceType);
        // Two-Way Authentication
        HttpsUtil httpsUtil = new HttpsUtil();
        httpsUtil.initSSLConfigForTwoWay();

        //Please make sure that the following parameter values have been modified in the Constant file.

        String urlDelete = Constant.DELETE_DEVICE + "/" +deviceId;

        Map<String, String> header = new HashMap<>();
        header.put(Constant.HEADER_APP_KEY, token.getAppId());
        header.put(Constant.HEADER_APP_AUTH, "Bearer" + " " + token.getToken());

        StreamClosedHttpResponse responseDelete = httpsUtil.doDeleteGetStatusLine(urlDelete, header);

        logger.info("StatusLine:"+responseDelete.getStatusLine()+" response content:"+responseDelete.getContent());
        return responseDelete.getContent();
    }

    public String subscribe(String deviceType){
        String bodySubscribe = handler(ConstantSecond.DEVICE_ADDED,ConstantSecond.DEVICE_ADDED_CALLBACK_URL,deviceType);
        bodySubscribe=bodySubscribe+ handler(ConstantSecond.DEVICE_INFO_CHANGED,ConstantSecond.DEVICE_INFO_CHANGED_CALLBACK_URL,deviceType);
        bodySubscribe=bodySubscribe+  handler(ConstantSecond.DEVICE_DATA_CHANGED,ConstantSecond.DEVICE_DATA_CHANGED_CALLBACK_URL,deviceType);
        bodySubscribe=bodySubscribe+  handler(ConstantSecond.DEVICE_DELETED,ConstantSecond.DEVICE_DELETED_CALLBACK_URL,deviceType);
        return bodySubscribe;
    }
    
    private String handler(String notifyType,String callbackUrl,String deviceType){
        String bodySubscribe = "";
        TelecomToken token = getAppId(deviceType);
        try {
            HttpsUtil httpsUtil = new HttpsUtil();
            httpsUtil.initSSLConfigForTwoWay();
            // Authentication，get token
            //Please make sure that the following parameter values have been modified in the Constant file.
            String urlSubscribe = ConstantSecond.SUBSCRIBE_NOTIFYCATION;

            Map<String, Object> paramSubscribe = new HashMap<>();
            paramSubscribe.put("notifyType", notifyType);
            paramSubscribe.put("callbackUrl", callbackUrl);

            String jsonRequest = JsonUtil.jsonObj2Sting(paramSubscribe);

            Map<String, String> header = new HashMap<>();
            header.put(ConstantSecond.HEADER_APP_KEY, token.getAppId());
            header.put(ConstantSecond.HEADER_APP_AUTH, "Bearer" + " " +token.getToken());

            HttpResponse httpResponse = httpsUtil.doPostJson(urlSubscribe, header, jsonRequest);

            bodySubscribe = httpsUtil.getHttpResponseBody(httpResponse);

            logger.info(httpResponse.getStatusLine()+"SubscribeNotification: " + notifyType);
            logger.info(bodySubscribe);
            System.out.println();
        }catch (Exception e){
            e.printStackTrace();
        }
        return bodySubscribe;
    }

    public TelecomToken getAppId(String deviceType){
        String appid=null;
        String token=null;
        if (StringUtils.isEmpty(deviceType)){
            appid=ConstantSecond.APPID.get(0);
            token=accessToken.get(0);
        }else if(StringUtils.equals("tb", deviceType)){
            appid=ConstantSecond.APPID.get(0);
            token=accessToken.get(0);
        }else if(StringUtils.equals("ln", deviceType)){
            appid=ConstantSecond.APPID.get(1);
            token=accessToken.get(1);
        }
        return new TelecomToken(appid,token);
    }

}
